package gui;

import information.Data;
import information.Job;
import information.JobDateComparator;
import information.JobDistrictComparator;
import information.JobLocationComparator;
import information.JobRegionComparator;
import information.User;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.ScrollPaneConstants;

import actions.HomeAction;
import actions.LoginAction;
import actions.PreviousAction;

/**
 * A frame for the gui of the Urban Parks program. This frame will display panels
 * of information to the user to navigate through the system. 
 * 
 * @author Natalie
 * @author Christian
 */
@SuppressWarnings("serial")
public class Frame extends JFrame {
	
	public static final int FRAME_HEIGHT = 750;
	public static final int FRAME_WIDTH = 1000;
	
	private static final String TITLE = "Urban Parks System";
	
	/**
	 * The data stored in the program. 
	 */
	private Data myData;
	
	/**
	 * A Panel for the center of the frame to control the layout. 
	 */
	private JPanel myCenterPanel;
	
	/**
	 * The User specific panel. 
	 */
	private UserPanel myUserPanel;
	
	/**
	 * A panel to display the calendar. 
	 */
	private CalendarPanel myCalendarPanel;
	
	/**
	 * The previous action taken, will be used for the previous button. 
	 */
	private AbstractAction myPreviousAction;
	
	/**
	 * Constructs a frame for the program. 
	 * 
	 * @author Natalie
	 * @param theData The data for the system. 
	 */
	public Frame(final Data theData) {
		super(TITLE);
		myData = theData;
		setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setLayout(new BorderLayout());
		myCenterPanel = new JPanel(new FlowLayout());
		add(myCenterPanel);
	}
	
	/**
	 * Starts the program and displays a login box.  
	 * @author Natalie
	 * @author Christian (added scrollbar code)
	 */
	public void start() {
		JPanel loginPanel = new JPanel(new GridLayout(2, 2));
		loginPanel.setPreferredSize(new Dimension(300, 50));
		JLabel lemail = new JLabel("Email: ");
		JTextField email = new JTextField();
		JButton login = new JButton(new LoginAction(this, email));
		JLabel blank = new JLabel();
		loginPanel.add(lemail);
		loginPanel.add(email);
		loginPanel.add(blank);
		loginPanel.add(login);
		myCenterPanel.add(loginPanel);
		JScrollPane scroller = new JScrollPane(myCenterPanel);
		scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
		getContentPane().add(scroller);
		pack();
	}
	
	/**
	 * Creates the initial home screen for the logged in user's type and adds a toolbar to the screen. 
	 * 
	 * @param theUsersActions A list of the actions the logged in user can take. 
	 * @author Natalie
	 */
	public void createOptions(List<AbstractAction> theUsersActions) {
		myUserPanel = new UserPanel(theUsersActions);
		myUserPanel.createHome();
		JToolBar toolbar = new JToolBar();
		toolbar.add(new JButton(new HomeAction(this)));
		myPreviousAction = new HomeAction(this);
		toolbar.add(new JButton(new PreviousAction(this)));
		myCenterPanel.removeAll();
		add(toolbar, BorderLayout.SOUTH);
		myCenterPanel.add(myUserPanel);
		pack();
	}
	
	/**
	 * Displays a list of volunteers that aren't blackballed.
	 * @author Christian
	 */
	public void displayVolunteers() {
		Set<User> goodVolunteers = new HashSet<User>();
		for (User volunteer : myData.getVolunteers()) {
			if (!volunteer.isBlackballed()) {
				goodVolunteers.add(volunteer);
			}
		}
		myUserPanel.displayVolunteers(this, goodVolunteers);
		pack();
	}
	
	/**
	 * Displays a form for a Park Manager to fill out with all of a new jobs information.
	 * @author Natalie
	 */
	public void displayJobForm() {
		myUserPanel.displayJobForm(this);
		pack();
	}
	
	/**
	 * Displays a screen telling the user their task has been completed successfully. 
	 * @author Natalie
	 */
	public void displaySuccess(final String theMessage) {
		myUserPanel.displaySuccess(theMessage);
		pack();
	}
	
	/**
	 * Displays the calendar to the user. 
	 * @author Natalie
	 */
	public void displayCalendar() {
		myCenterPanel.removeAll();
		myCalendarPanel = new CalendarPanel(myData);
		myCenterPanel.add(myCalendarPanel);
		pack();
	}
	
	/**
	 * Displays the home screen.
	 * @author Natalie 
	 */
	public void goHome() {
		if(myCalendarPanel != null) {
			myCenterPanel.remove(myCalendarPanel);
			myCenterPanel.add(myUserPanel);
			myCenterPanel.repaint();
		}
		myUserPanel.createHome();
		pack();
	}
	
	/**
	 * Returns all of the programs data. 
	 * 
	 * @return The Data object. 
	 * @author Natalie
	 */
	public Data getData() {
		return myData;
	}
	
	/**
	 * Displays a list of jobs for volunteer to browse.
	 * User story 7, Business rules 6, 7, 3
	 * The list is limited to jobs with openings AND are not overlapping dates of jobs
	 * the volunteer is signed up for.
	 * @author Christian
	 * @param theSortCriteria
	 */
	public void browseJobs(final List<String> theSortCriteria) {
		List<Job> availableJobs = new ArrayList<Job>();
		Set<Job> userJobs = myData.getUserJobs();
		for (Job job : myData.getCurrentJobs()) {
			//check if job has openings
			if ((job.getLightNumber() - job.getPositionsFilled(0)) > 0 ||
					(job.getMediumNumber() - job.getPositionsFilled(1)) > 0 ||
					(job.getHeavyNumber() - job.getPositionsFilled(2)) > 0) {
				boolean overlapping = false;
				Iterator<Job> jobIt = userJobs.iterator();
				//check if job has overlapping dates with any jobs the user has applied for
				while (jobIt.hasNext() && overlapping == false) {
					overlapping = job.isOverlappingDateRange(jobIt.next());
				}
				if (overlapping == false) {
					availableJobs.add(job);
				}
			}
		}
		if (theSortCriteria != null) {
			int criteriaSize = theSortCriteria.size();
			JobMultiComparator mc = new JobMultiComparator();
			for (int i = 0; i < criteriaSize; i++) {
				if (theSortCriteria.get(i).equals("Region")) {
					mc.addComparator(new JobRegionComparator());
				} else if (theSortCriteria.get(i).equals("District")) {
					mc.addComparator(new JobDistrictComparator());
				} else if (theSortCriteria.get(i).equals("Park")) {
					mc.addComparator(new JobLocationComparator());
				} else { //dates
					mc.addComparator(new JobDateComparator());
				}
			}
			Collections.sort(availableJobs, mc);
		}
		myUserPanel.browseJobs(availableJobs, theSortCriteria, this);
		pack();
	}
	
	/**
	 * Displays the jobs a volunteer is signed up for. 
	 * @author Natalie
	 */
	public void displayJobsForVolunteer() {
		myUserPanel.displayJobs(myData.getUserJobs());
		pack();
	}
	
	/**
	 * Display a list of blackballed volunteers.
	 * @author Christian
	 */
	public void displayBlackballedVolunteers() {
		Set<User> blackballedVolunteers = new HashSet<User>();
		for (User volunteer : myData.getVolunteers()) {
			if (volunteer.isBlackballed()) {
				blackballedVolunteers.add(volunteer);
			}
		}
		myUserPanel.displayVolunteerList(blackballedVolunteers, "Blackballed Volunteers");
		pack();
	}
	
	/**
	 * Displays the logged-in park managers pending jobs on the user panel. 
	 * 
	 * @author Natalie
	 */
	public void displayPendingJobs() {
		myUserPanel.displayJobs(myData.getUserJobs());
		pack();
	}
	
	/**
	 * Returns the previous action that was taken by the User. Used for the previous button. 
	 * 
	 * @return The previous action. 
	 * @author Natalie
	 */
	public AbstractAction getPreviousAction() {
		return myPreviousAction;
	}
	
	/**
	 * Sets the previous action taken by the User. Used for the previous button. 
	 * 
	 * @param theAction The previous action taken. 
	 * @author Natalie
	 */
	public void setPreviousAction(final AbstractAction theAction) {
		myPreviousAction = theAction;
	}
}
